from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings         # 配置文件需要更换生产模式
from django.shortcuts import render
from rest_framework.generics import RetrieveAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView


# 获取qq登陆页面的接口
from oauth import serializers
from oauth.models import OAuthQQUser

# from oauth.utils import generate_encrypted_openid
from oauth.utils import generate_encrypted_openid


class QQURLView(APIView):  # 因不涉及数据库的相关操作所以继承于父类APIView

    # 获取qq登陆页面的接口
    # /auth/qq/authorization/next=xxx
    def get(self, request):    # get 方法
        '''获取qq登陆的url地址'''

        # next = request.GET.get()    query_params 相当于 GET
        next = request.query_params.get('next')

        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)  # sate 表示登陆成功以后需要进入的地址一般是回到网站首页

        # qq登陆的url地址
        login_url = oauth.get_qq_url()

        # 将获取到的qq登陆地址返回给前端

        return Response({'login_url': login_url})


# 获取 QQ认证的接口
class QQUserView(APIView):
    # /oauth/qq/user/code =xxx
    def get(self, request):
        ''' QQ认证的接口 '''

        # 1. 获取请求参数：code 在request中
        code = request.query_params.get('code')    # query_params 查询字符串是一个正则
        print('code的值为%s'%code)

        # 2. 校验code参数
        if not code:
            # print(code)

            return Response({'message': 'code参数不能为空'}, status=400)

        # 创建第三方sdk oauth 为 OAuthQQ 对象 中含获取参数的方法 所以拿下来  通过第三方包简化
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)  # sate 表示登陆成功以后需要进入的地址一般是回到网站首页
        try:
            # 3.使用QQ登录sdk， 通过code获取access_token  OAuthQQ类下有一个 get_access_token方法 中有code的值
            access_token = oauth.get_access_token(code)

            # 4.使用QQ登录sdk， 通过access_token获取openid
            #     def get_open_id(self, access_token) 源码中是这么定义的 所以先导access_token 后回去openid
            openid = oauth.get_open_id(access_token)
            # openid = oauth.get_open_id(openid)
            print(openid)
        except:
            return Response({'message': '获取openid出错'}, status=400)

        # 5.1根据openid，从映射表中查询绑定的美多用户对象
        try:
            qquser = OAuthQQUser.objects.get(openid=openid)

        except OAuthQQUser.DoesNotExist:
            # - 查询不到美多用户，说明是第一次使用QQ登录，则返回openid, 等待后续用户的绑定操作
            # 使用itsdangerous签名数据后，在响应给客户端
            openid = generate_encrypted_openid(openid)
            return Response({'openid': openid})

        else:
            # 能查到绑定后的用户生成jwt
            from rest_framework_jwt.settings import api_settings
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 生payload部分的方法(函数)
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 生成jwt的方法(函数)

            # - 能查询到美多用户，则生成并响应：jwt，user_id, username，完成QQ登录流程
            user = qquser.user   # 关联美多用户的对象 通过关联属性获取

            payload = jwt_payload_handler(user)  # 生成payload, 得到字典
            token = jwt_encode_handler(payload)  # 生成jwt字符串

            # jwt 的响应字段
            context = {
                'token': token,
                'user_id': user.id,
                'user_name': user.username
            }

            # 将生成的jwt返回 给浏览器
            return Response(context)

    # POST /oauth/qq/user  前端通过表单将4个参数传过来 所以这里不需要post(self, request)传参
    # 在视图中定义和调用序列化器 在序列化器中定义功能
    def post(self, request):

        '''
        一、视图
            # 1. 创建序列化器  /apps/oauth/serializers.py
            #  data用来获取表单传过来的的4个数据  data = request.data 固定写法
            # 2. 校验请求参数是否合法: serializer.is_valid()
            # 3. 绑定openid与美多用户:  serializer.save()   -> serializer.create()
            # 4. 生成并响应 jwt, user_id, username，完成QQ登录

        '''

        # 1. 创建序列化器
        #  data用来获取表单传过来的的4个数据  data = request.data 固定写法
        s = QQUserSerializer(data=request.data)

        # 2. 校验请求参数是否合法: serializer.is_valid()
        s.is_valid(raise_exception=True)  # is_valid() 调用 def validate(self, attrs): 这个方法

        # 3. 绑定openid与美多用户:  serializer.save()   -> serializer.create()
        user = s.save()  # 通过save方式将openid保存在表中并返回绑定的美多用户对象

        # 4. 生成并响应 jwt, user_id, username，完成QQ登录

        # 生成jwt
        from rest_framework_jwt.settings import api_settings

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 生payload部分的方法(函数)
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 生成jwt的方法(函数)

        payload = jwt_payload_handler(user)  # 生成payload, 得到字典
        token = jwt_encode_handler(payload)  # 生成jwt字符串

        # jwt 的响应字段
        context = {
            'token': token,
            'user_id': user.id,
            'user_name': user.username
        }

        # 将生成的jwt返回 给浏览器
        return Response(context)


